package edu.xidian.onlinedocument.utils.ot.internal;

import edu.xidian.onlinedocument.utils.ot.internal.operations.ChangesList;

import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;

/**
 * 链式反应
 *
 * Vm: m版本文件内容
 * OPm: 服务器记录的对m版本的操作
 * BOPm: B客户端对Vm的修改
 * DOOP: 服务器OT变换后执行操作
 * REOP：B客户端OT变换后执行操作
 *
 * Vm * OPm * OT(OPm, BOPm) = Vm * BOPm * OT(BOPm, OPm)
 * DOOP = OT(OPm, BOPm)
 * REOP = OT(BOPm, OPm)
 * { Vm * OPm * DOOP * OT(DOOP, OPm+1) =
 * Vm * OPm * OPm+1 * OT(OPm+1, DOOP) =
 * Vm * BOPm * REOP * OT(DOOP, OPm+1) }
 * DOOP = OT(OPm+1, DOOP)
 * REOP = REOP * OT(DOOP, OPm+1)
 */
public class ChainReaction {
    private ChainReaction(){
    }

    public static ChangesList chainReaction(ChangesList oldChanges, List<ChangesList> localChanges) {
        ChangesList res = oldChanges;
        int oldRevision = oldChanges.getRevision();

        if (oldRevision < localChanges.get(0).getRevision()) {
            return null;
        }
        while (oldRevision > localChanges.get(0).getRevision()) {
            localChanges.remove(0);
        }
        for (ChangesList A : localChanges) {
            Transform.Result trans = Transform.transform(A, res);
            res = trans.getRight();
            res.setRevision(++oldRevision);
        }

        // 假设B的版本为3，服务器最新版本为10
        // 获取同版本的操作，这里记为A，版本为3
        // ChangesList conflict = null;
        // 对同版本的操作做transform
        // 得到版本为4的B+
        // Transform.Result result = Transform.transform(conflict, oldRevisionChanges);
        // result.getRight().setRevision(newRevision + 1);
        // 存储B+
        // res.add(result.getRight());
        // 从已有冲突的操作A的下一个原有操作出发，到当前服务器最新的操作，都进行transform
        // 与上面的transform不同，这里由于B+是由A和B做transform得到的，所以做transform时应该作为left
        /*
        for (int i = oldRevision; i <= latestRevision; i++) {
            // 获取同版本的操作，假设原操作版本为4，记为C
            conflict = localChanges.get()
            // 对同版本的操作做transform，这里将B+放在left，C放在right，得到result(B++,C+)
            result = Transform.transform(res.get(res.size() - 1), conflict);
            result.getRight().setRevision(i + 1);
            // 存储C+
            res.add(result.getRight());
        }
         */
        // 注意，这里要将lastSaveRevision设为B的版本，因为与B版本相同的A操作之后的操作都被改变了
        // this.setLastSaveRevision(newRevision);
        return res;
    }
}
